<template>
  <div :style="state.style">
    <el-upload
      ref="uploadRef"
      :accept="state.acceptOptions"
      :action="state.action"
      :auto-upload="autoUpload"
      :before-upload="handleBeforUpload"
      class="upload-content"
      :class="{
        uploadStyle: state.showBtnDeal,
        disUploadStyle: state.hiddenBtnDeal
      }"
      :close-on-click-modal="false"
      :data="state.data"
      :file-list="state.fileList"
      :headers="state.headers"
      :limit="state.limit"
      list-type="text"
      :multiple="true"
      :name="state.name"
      :on-change="handleChange"
      :on-error="handleError"
      :on-exceed="handleExceed"
      :on-remove="handleRemove"
      :on-success="handleSuccess"
    >
      <template #tip>
        <div class="el-upload__tip" v-if="alertShow">
          可上传文件{{ accept }}，最多可上传{{
            limit
          }}个文件，每个文件不可大于{{ size }}M`
        </div>
      </template>
      <template #file="{ file }">
        <el-row>
          <el-col :span="16">{{ file.name }}</el-col>
          <el-col :span="8" v-if="file.response && file.response.code === 200">
            <el-row>
              <el-col :span="12">
                {{ file.response.data.createTime }}
              </el-col>
              <el-col :span="12">
                <div style="display: flex; justify-content: space-around">
                  <span @click="handlePreview(file.response.data)">
                    <el-icon><ZoomIn /></el-icon>
                  </span>
                  <span @click="handleDelete(file.response.data)">
                    <el-icon><Delete /></el-icon>
                  </span>
                  <span @click="handleDownload(file.response.data)">
                    <el-icon><Download /></el-icon>
                  </span>
                </div>
              </el-col>
            </el-row>
          </el-col>
          <el-col :span="8" v-else>
            <el-row>
              <el-col :span="12">
                {{ file.createTime }}
              </el-col>
              <el-col :span="12">
                <div style="display: flex; justify-content: space-around">
                  <span @click="handlePreview(file)">
                    <el-icon><ZoomIn /></el-icon>
                  </span>
                  <el-button
                    icon="Delete"
                    :disabled="disabled"
                    @click="handleDelete(file)"
                  />
                  <span @click="handleDownload(file)">
                    <el-icon><Download /></el-icon>
                  </span>
                </div>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </template>
      <el-button
        v-if="!state.hiddenBtnDeal"
        :disabled="disabled"
        type="primary"
        icon="plus"
        >选择文件</el-button
      >
    </el-upload>
  </div>
</template>
<script setup name="FileUpload">
import _ from "lodash";
import { queryFileList, deleteFile, downloadFile } from "@/api/admin/cms/file/";
import { useMessage, useMessageBox } from "@/hooks/message";
import { cloneObject } from "@/utils/common";
import { Delete, Download, Plus, ZoomIn } from "@element-plus/icons-vue";
const { VITE_API_URL } = import.meta.env;
let apiBaseUrl = VITE_API_URL;
import { getTokenValue } from "@/utils/auth";

const props = defineProps({
  fileTypeCode: {
    type: String,
    default: ""
  },
  height: {
    type: Number,
    default: 180
  },
  limit: {
    type: Number,
    default: 5
  },
  size: {
    type: Number,
    default: 2
  },
  autoUpload: {
    type: Boolean,
    default: false
  },
  alertShow: {
    type: Boolean,
    default: true
  },
  disabled: {
    type: Boolean,
    default: false
  },
  storageMode: {
    type: String,
    default: ""
  },
  accept: {
    type: Array,
    default: function () {
      return [".pdf"];
    }
  }
});

const emits = defineEmits(["success", "remove"]);

const uploadRef = ref(null);

const state = reactive({
  acceptOptions: props.accept.join(","),
  style: {
    "max-height": `${props.height}px`,
    "overflow-y": "auto",
    width: "100%"
  },
  showBtnDeal: true,
  hiddenBtnDeal: false,
  data: {
    id: "",
    fileFlag: "0",
    objectId: "",
    type: "",
    fileTypeCode: props.fileTypeCode,
    fileTypeName: "",
    nameType: "",
    extension: "",
    fileName: "",
    fileSize: "",
    storageMode: props.storageMode,
    storageDir: ""
  },
  queryParams: {
    id: "",
    objectId: "",
    fileTypeCode: props.fileTypeCode
  },
  onChange: false,
  action: `${apiBaseUrl}/admin/file/upload`,
  limit: props.limit,
  size: props.size,
  name: "file",
  headers: {},
  token: "",
  fileList: [],
  successNum: 0,
  errorNum: 0
});

const queryFileData = async params => {
  await queryFileList(params).then(res => {
    if (res.code === 200) {
      const fileList = [];
      res.data.forEach(item => {
        const fileExistsList = state.fileList.filter(item => {
          return item.id;
        });
        if (fileExistsList.length < 1) {
          const file = { name: "", url: "", id: "", status: "" };
          file.name = item.fileName;
          file.id = item.id;
          file.status = "success";
          file.extension = item.extension;
          file.createTime = item.createTime;
          file.storageMode = item.storageMode;
          if (file.storageMode != "db") {
            file.url = item.storageFileUrl;
          } else {
            file.url = `${apiBaseUrl}/admin/file/preview?id=${item.id}`;
          }
          fileList.push(file);
        }
      });
      if (fileList.length > 0) {
        state.fileList = fileList;
      }
      if (state.fileList.length >= state.limit) {
        state.showBtnDeal = false;
        state.hiddenBtnDeal = true;
      } else {
        state.showBtnDeal = true;
        state.hiddenBtnDeal = false;
      }
    } else {
      state.fileList = [];
    }
  });
};

const handleChange = (file, fileList) => {
  if (file.size > 1048576 * state.size) {
    state.fileList = fileList.filter(item => {
      return item.name !== file.name;
    });
    useMessageBox().warning(`上传文件大小不能超过${state.size}MB!`);
  }
  const fileNameArray = file.name.split(".");
  const fileType = `.${fileNameArray[fileNameArray.length - 1]}`;
  if (props.accept.indexOf(fileType.toLowerCase()) === -1) {
    state.fileList = fileList.filter(item => {
      return item.uid !== file.uid;
    });
    useMessageBox().warning(`请选择合适的文件!`);
  }
  const needUploadfileList = fileList.filter(item => {
    return item.status != "success";
  });
  if (needUploadfileList && needUploadfileList.length > 0) {
    state.onChange = true;
  } else {
    state.onChange = false;
  }
  if (fileList.length >= state.limit) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
};

const handleError = (err, file) => {
  state.errorNum = state.errorNum + 1;
  useMessageBox().warning(
    `文件[${file.raw.name}]上传失败,文件大小为${_.round(
      file.raw.size / 1024,
      0
    )}KB`
  );
};

const handleExceed = files => {
  useMessageBox().warning(`当前限制选择 ${state.limit} 个文件，本次选择了
             ${files.length}
             个文件`);
};

const getFileListItem = fileName => {
  const fileItem = state.fileList.filter(item => {
    return item.status === "success" && item.name === fileName;
  });
  return fileItem;
};

const handleRemove = async (file, fileList) => {
  const fileItem = getFileListItem(file.name);
  if (file && file.status === "success" && file.id) {
    await deleteFile(file.id);
  } else if (fileItem && fileItem.length > 0) {
    await deleteFile(fileItem.map(item => item.id).join(","));
  }
  const needUploadfileList = fileList.filter(item => {
    return item.status != "success";
  });
  if (needUploadfileList && needUploadfileList.length > 0) {
    state.onChange = true;
  } else {
    state.onChange = false;
  }
  if (fileList.length >= state.limit) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
  emits("remove", {});
};

const handleSuccess = (res, file, fileList) => {
  if (res.code === 200) {
    state.successNum = state.successNum + 1;
    setTimeout(() => {
      useMessage().success(`上传完成! 共${fileList.length}个文件`);
    }, 1000);
    const item = res.data;
    let fileExistsList = [];
    if (state.fileList.length > 0) {
      fileExistsList = state.fileList.filter(file => {
        return file.id === item.id;
      });
    }
    // fileList中不存在此文件
    if (fileExistsList.length < 1) {
      const fileitem = {
        name: "",
        url: "",
        id: "",
        status: "",
        extension: "",
        createTime: "",
        storageMode: "",
        uid: file.uid
      };
      fileitem.name = item.fileName;
      fileitem.id = item.id;
      fileitem.status = "success";
      fileitem.extension = item.extension;
      fileitem.createTime = item.createTime;
      fileitem.storageMode = item.storageMode;
      if (fileitem.storageMode === "db") {
        fileitem.url = `${apiBaseUrl}/admin/file/preview?id=${item.id}`;
      } else {
        fileitem.url = item.storageFileUrl;
      }
      state.fileList.push(fileitem);
      if (fileList.length >= state.limit) {
        state.showBtnDeal = false;
        state.hiddenBtnDeal = true;
      } else {
        state.showBtnDeal = true;
        state.hiddenBtnDeal = false;
      }
      emits("success", res.data, file);
    }
  } else {
    useMessageBox().warning(res.msg);
  }
};

const handleBeforUpload = file => {
  state.data.id = "";
  state.data.fileName = file.name;
  state.data.fileFlag = "0";
  state.data.fileSize = file.size;
  state.data.type = file.type;
};

const init = (row, readonly) => {
  if (readonly) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
  if (row) {
    cloneObject(state.data, row);
    cloneObject(state.queryParams, row);
  }
};

const load = () => {
  queryFileData(state.queryParams);
};

const submitUpload = objectId => {
  if (objectId) {
    state.data.objectId = objectId;
  }
  if (state.onChange) {
    uploadRef.value.submit();
  }
};

const handleDelete = async file => {
  if (file && file.id) {
    await deleteFile(file.id);
  }
  state.fileList = state.fileList.filter(item => item.id != file.id);
  if (state.fileList.length >= state.limit) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
};

const handlePreview = file => {
  window.open(file.url, "_blank");
};

const handleDownload = file => {
  const loadingInstance = ElLoading.service();
  downloadFile({ id: file.id })
    .then(res => {
      const blob = new Blob([res]);
      // 将链接地址字符内容转变成blob地址
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = `${file.name}`; // 下载文件的名字
      link.click();
      loadingInstance.close();
    })
    .catch(e => loadingInstance.close());
};

onMounted(() => {
  const token = getTokenValue();
  state.headers["Authorization"] = `Bearer ${token}`;
  state.token = token;
});

defineExpose({
  state,
  submitUpload,
  init,
  load
});
</script>
<style lang="scss" scoped>
.disUploadStyle {
  :deep(.el-upload) {
    display: none;
  }
}
</style>
